#include "sparse_matrix.h"

/* Memory allocation for sparse matrix */
sparse_matrix_lst* allocate_sparse_matrix_lst(int n)
{
	sparse_matrix_lst* sparse_matrix = (sparse_matrix_lst*)malloc(sizeof(sparse_matrix_lst));
	assert (sparse_matrix != NULL);
	sparse_matrix->cols = (cell_t**)calloc(n, sizeof(cell_t));
	assert (sparse_matrix->cols != NULL);
	sparse_matrix->rows = (cell_t**)calloc(n, sizeof(cell_t));
	assert (sparse_matrix->rows != NULL);
	sparse_matrix->n = n;
	return sparse_matrix;
}

/*Recursive release of the insides of the matrix*/
void free_cells(cell_t* cell)
{
	if (cell->col_next == NULL)
	{
		return;
	}

	free_cells(cell->col_next);

	free(cell->col_next);
	cell->col_next = NULL;
}

/* Releasing the main vectors of the sparse matrix
and all the cells inside them */
void free_sparse_matrix_lst(sparse_matrix_lst* matrix)
{
	int i = 0;
	int rows_no = matrix->n;
	
	/*Going over the rows releasing allocated info*/
	for (i = rows_no - 1; i >= 0; --i)
	{
		if (matrix->rows[i] != NULL)
		{
			free_cells(matrix->rows[i]);
		}
	}

	free(matrix->cols);
	free(matrix->rows);
	free(matrix);
}

/* Multiplication of sparse matrix by vector*/
void  mult_sparse_list(const sparse_matrix_lst* A, const elem* v, elem* result)
{
	int size = A->n;
	int sum = 0;
	int i = 0;
	cell_t* current_cell = NULL;

	for(i = 0; i < size; i++)
	{
		sum = 0;
		current_cell = A->rows[i];
		while(current_cell != NULL)
		{
			sum += current_cell->value * v[current_cell->colind];
			current_cell = current_cell->col_next;
		}
		result[i] = sum;
	}

}

